#ifndef SPTLIB
#define SPTLIB

#include <algorithm>
#include <iostream>
#include <fstream>
#include <map>
#include <cstdarg>
#include <stdexcept>
#include <sstream>
#include <string.h>
#include <vector>
#include <cmath>

#define MAXPARMLENGTH 65535

#pragma pack (1)

typedef std::map<std::string, std::string> parmMap;

char * merge( int args, ...) ;

std::string trim(std::string str, std::string whitespace = " \t\f\v\n\r") ;
std::string trim(char * str, std::string whitespace = " \t\f\v\n\r") ;

int mInt(std::string val) ;

parmMap smLoadParms(const char * parmfile, char * delim = (char *)"=") ;
parmMap smLoadParms(std::string parmfile, char * delim = (char*)"=") ;
parmMap smLoadParms(const char * parmfile, parmMap parms, char * delim = (char*)"=") ;
parmMap smLoadParms(std::string parmfile, parmMap parms, char * delim = (char*)"=") ;
parmMap smParms(int argc, char *argv[], bool autoload = false, char * delim = (char *)"=") ;
parmMap smParms(int argc, char *argv[], parmMap parms, char * delim = (char *)"=") ;

void asDefault(parmMap &parmmm, std::string key, std::string val) ;
void parmDump(parmMap parms) ;
void parmDump(parmMap parms, const char * filename) ;

void upcase(std::string &str) ;
void downcase(std::string &str) ;

int convertToSASDate (int yyyymmdd) ;
class smDate {
	public: int sasDate;
	public: int tagDate;
	public: int year;
	public: int month;
	public: int day;
	void init(int i) ;
	void strinit(std::string dt) ;
	public: smDate() ;
	public: smDate(int i);
	public: smDate(std::string dt);
	public: smDate(char * dt);
	/*
	 * The following two functions are modified from code Copyright (c) 2008 by Claus Tondering
	 *   (claus@tondering.dk) under the Boost Software License  - Version 1.0 - August 17th, 2003
	*/
	/*
	 * date_to_jdn:
	 * Calculates the Julian Day Number for a given date.
	 * Input parameters:
	 *     Calendar style (JULIAN or GREGORIAN)
	 *     Year (must be > -4800). The year 1 BC must be given as 0, the
	 *         year 2 BC must be given as -1, etc.
	 *     Month (1..12)
	 *     Day (1..31)
	 * Returns:
	 *     Julian Day Number
	 *
	 * Reference: Section 2.16.1 of version 2.9 of the FAQ.
	 */
	int date_to_jdn(int year, int month, int day);
	/*
	 * jdn_to_date:
	 * Calculates the date for a given Julian Day Number.
	 * Input parameter:
	 *     Calendar style (JULIAN or GREGORIAN)
	 *     Julian Day Number
	 * Output parameters:
	 *     Address of year. The year 1 BC will be stored as 0, the year
	 *         2 BC will be stored as -1, etc.
	 *     Address of month (1..12)
	 *     Address of day (1..31)
	 *
	 * Reference: Section 2.16.1 of version 2.9 of the FAQ.
	 */
	void jdn_to_date(int JD, int *year, int *month, int *day);
	void date_to_sasdate() ;
	void sasdate_to_date() ;
};

// 20 is 1 MiB
#define OBUFSIZE 24
class oBuffer {
  public:
    char * buffer;
    int currpos;
    std::ofstream outF;
    int OUTBUFSIZE;
    
  public:
    void open(std::string fileName, std::ios_base::openmode mode = std::ios_base::out|std::ios::binary,
			long int log2_bufsize = OBUFSIZE) ;
    void flush();
    void write(const char * el, int el_size) ;
      void close() ;
      oBuffer& operator<< (std::string str);
      oBuffer& operator<< (char* str);
      oBuffer& operator<< (char str);
      oBuffer& operator<< (float& num);
      oBuffer& operator<< (double& num);
      oBuffer& operator<< (long double& num);
      oBuffer& operator<< (short& num);
      oBuffer& operator<< (unsigned short& num);
      oBuffer& operator<< (int& num);
      oBuffer& operator<< (unsigned int& num);
      oBuffer& operator<< (long& num);
      oBuffer& operator<< (unsigned long& num);
      oBuffer& operator<< (long long& num);
      oBuffer& operator<< (unsigned long long& num);
      oBuffer& operator<< (std::stringstream& strb);
  };

std::string IntToStr(int x) ;

#endif /* ifndef SPTLIB */
